<template>
    <el-dialog v-model="props.dialogVisible" title="地图工具" width="80%" destroy-on-close @closed="handleCancel">
        <div class="relative w-full" style="height: 480px">
            <div id="container" class="w-full h-full" style="border: 1px solid #d9d9d9; border-top: 0"></div>
            <div class="absolute w-30" style="top: 30px; left: 20px">
                <div id="panel" class="flex flex-col">
                    <div id="searchBar">
                        <input id="autoinput" style="width: 100%" :value="searchKey" placeholder="请输入关键字进行搜索" />
                    </div>
                    <div id="searchResults"></div>
                </div>
            </div>

            <div class="absolute w-30" style="bottom: 30px; right: 7rem">
                <div v-if="mapType === 1" class="flex flex-col">
                    <el-text class="mx-1" type="success">{{ tipTxt }}</el-text>
                    <div class="flex">
                        <!-- <el-button type="primary" size="small" plain @click="removeLastPlygon">删除上个多边形</el-button>
            <el-button type="primary" size="small" plain @click="removeAllPlygon">清空全部多边形</el-button> -->

                        <el-button type="primary" size="small" plain @click="editLine">编辑多边形</el-button>
                        <el-button type="primary" size="small" plain @click="closeEditor">编辑完成</el-button>
                    </div>
                </div>

                <div v-if="mapType === 2" class="flex">
                    <el-button type="primary" size="small" plain @click="editLine">编辑折线</el-button>
                    <el-button type="primary" size="small" plain @click="closeEditor">编辑完成</el-button>
                </div>
            </div>
        </div>
        <template #footer>
            <div class="dialog-footer">
                <el-button @click="handleCancel">取消</el-button>
                <el-button type="primary" :disabled="okDisabled" @click="handleConfirm">完成</el-button>
            </div>
        </template>
    </el-dialog>
</template>
<script setup>
import AMapLoader from '@amap/amap-jsapi-loader';
/*在Vue3中使用时,需要引入Vue3中的shallowRef方法(使用shallowRef进行非深度监听,
因为在Vue3中所使用的Proxy拦截操作会改变JSAPI原生对象,所以此处需要区别Vue2使用方式对地图对象进行非深度监听,
否则会出现问题,建议JSAPI相关对象采用非响应式的普通对象来存储)*/
import { shallowRef } from 'vue';
import { nextTick, onMounted, onUnmounted, reactive, ref, defineEmits, defineProps } from 'vue';
import { ElMessage } from 'element-plus';
import _ from 'lodash';

window._AMapSecurityConfig = {
    securityJsCode: '0c3f4b9e071157f7e2ff101d5042a52c',
};

const props = defineProps({
    dialogVisible: {
        type: Boolean,
        default: false,
    },
    mapType: {
        //0:取点  1:取面   2：划线
        type: Number,
        default: 0,
    },
    searchKey: {
        type: String,
        default: '',
    },
});

const $emits = defineEmits(['mapClose', 'mapConfirm']);

const tipTxt = ref('');

var poi = null;
var paths = [];
var overlays = [];
var mouseTool = null;
const current_position = ref([]);

let map = reactive(null);
function initMap() {
    window._AMapSecurityConfig = {
        securityJsCode: '5072bc1e694598ba764e8818a9970ac4',
    };
    AMapLoader.load({
        key: 'ed2e08abbd3c515a0895612c04811efd', // 申请好的Web端开发者Key，首次调用 load 时必填
        version: '2.0', // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
        // plugins:[''], // 需要使用的的插件列表，如比例尺'AMap.Scale'等
        AMapUI: {
            version: '1.1',
            plugins: [], // 需要加载的 AMapUI ui插件
        },
    })
        .then((AMap) => {
            map = new AMap.Map('container', {
                //设置地图容器id
                viewMode: '3D', //是否为3D地图模式
                zoom: 13, //初始化地图级别
                center: [113.808299, 34.791787], //初始化地图中心点位置
            });

            var autoOptions = {
                // 可选参数，你的搜索输入框dom的id(多数场景下只需要这一个参数即可)
                input: 'autoinput',
                // 可选参数，你的搜索输出框dom的id，用来展示提示的结果（默认的只有图里的文字，如果需要图片等，需要指定output）
                output: 'your_out_put_id',
                // 是否强制指定城市,设定city后有效
                citylimit: true,
                // 默认为true，表示是否在input位于页面较下方的时候自动将输入面板显示在input上方以避免被遮挡
                outPutDirAuto: true,
                // ···其他参数请翻阅文档
            };

            AMap.plugin(['AMap.PlaceSearch', 'AMap.AutoComplete'], function () {
                //无需再手动执行 search 方法，autoComplete 会根据传 input 对应的 DOM 动态触发 search
                var autoComplete = new AMap.AutoComplete(autoOptions);

                var placeSearch = new AMap.PlaceSearch({
                    map: map,
                    type: '', // 数据类别
                    pageIndex: 1,
                    pageSize: 10,
                });

                // 注册监听，当选中某条记录时会触发
                autoComplete.on('select', select);

                function select(e) {
                    // 获取到检索提示信息后，根据提示信息搜索精确地理位置
                    // 设置查询城市（防止查提示信息所在城市之外的城市）
                    placeSearch.setCity(e.poi.adcode);
                    // 检索地理信息
                    placeSearch.search(e.poi.name, function (status, result) {
                        // 获取查询到的结果
                        if (status == 'complete') {
                            // 精确地理信息为多条，placeSearch会将地理位置全部添加为地图Marker，如果需要触发点击时获取指定Marker的地理信息，可以添加markerClick事件
                            console.log(result.poiList.pois);

                            placeSearch.on('markerClick', function (e) {
                                // e.data中即为poi信息（=result.poiList.pois[i])
                                console.log(e.data);
                                // 当前点击的地图的marker
                                console.log(e.marker);
                            });
                        }
                    });
                }
            });
            AMapUI.loadUI(['misc/PoiPicker'], function (PoiPicker) {
                var poiPicker = new PoiPicker({
                    city: '新乡市',
                    input: 'autoinput',
                    placeSearchOptions: {
                        map: map,
                        pageSize: 5,
                    },
                    searchResultsContainer: 'searchResults',
                });

                poiPicker.on('poiPicked', function (poiResult) {
                    poiPicker.hideSearchResults();

                    var source = poiResult.source;
                    poi = poiResult.item;

                    if (source !== 'search') {
                        //suggest来源的，同样调用搜索
                        poiPicker.searchByKeyword(poi.name);
                    } else {
                        //console.log(poi);
                    }
                });
                // //初始化poiPicker
                poiPickerReady(poiPicker);
            });
            if (props.mapType === 1 || props.mapType === 2) {
                // 添加插件
                AMap.plugin(
                    [
                        'AMap.ToolBar',
                        'AMap.Scale',
                        // 'AMap.HawkEye',
                        'AMap.Geolocation',
                        'AMap.MapType',
                        'AMap.MouseTool',
                        'AMap.Geocoder',
                        'AMap.AutoComplete',
                        'AMap.PlaceSearch',
                        'AMap.PolylineEditor',
                        'AMap.PolygonEditor',
                    ],
                    function () {
                        //异步同时加载多个插件
                        // 添加地图插件
                        map.addControl(new AMap.ToolBar({ position: 'LB' })); // 工具条控件;范围选择控件
                        // map.addControl(new AMap.Scale()); // 显示当前地图中心的比例尺
                        // map.addControl(new AMap.HawkEye()); // 显示缩略图
                        map.addControl(new AMap.Geolocation()); // 定位当前位置
                        map.addControl(new AMap.MapType()); // 实现默认图层与卫星图,实时交通图层之间切换

                        // 以下是鼠标工具插件
                        mouseTool = new AMap.MouseTool(map);
                        // mouseTool.rule();// 用户手动绘制折线图,测量距离
                        // mouseTool.measureArea(); // 测量面积
                        openMouseTool(mouseTool);
                        mouseTool.on('draw', function (e) {
                            console.log('e.obj :>> ', e);
                            lastPlygon = e.obj;
                            var pa = e.obj.getPath();
                            var ca = pa.map((item) => {
                                return [item.lng, item.lat];
                            });
                            paths.push(ca);
                            overlays.push(e.obj);
                            if (props.mapType === 1) {
                                okDisabled.value = false;
                            }
                        });
                    },
                );
            }
            // 单击
            map.on('click', (e) => {
                // lng ==> 经度值  lat => 维度值
                current_position.value = [e.lnglat.lng, e.lnglat.lat];
            });

            // 实例化点标记
            // 第一种(封成函数来触发)
            function addMarker() {
                const marker = new AMap.Marker({
                    icon: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png',
                    position: current_position.value, // 这里我们通过上面的点击获取经纬度坐标,实时添加标记
                    // 通过设置 offset 来添加偏移量
                    offset: new AMap.Pixel(-26, -54),
                });
                marker.setMap(map);
            }
        })
        .catch((e) => {
            console.log(e);
        });
}

const okDisabled = ref(true);
const data = reactive({
    aMap: '',
    zoom: 13,
    center: [114.02, 33.01],
    address: {},
    auto: {},
    placeSearch: {},
    input: '',
    poiPicker: null,
});

onMounted(() => {
    nextTick(() => {
        initMap();
    });
});

onUnmounted(() => {
    map?.destroy();
});
function cut(value) {
    return value.slice(0, value.length - 1);
}
var lastPlygon;
const removeLastPlygon = () => {
    map.remove(lastPlygon);
    overlays = cut(overlays);
    if (overlays.length) {
        lastPlygon = overlays[overlays.length - 1];
        paths = cut(paths);
    } else {
        if (props.mapType === 1) {
            okDisabled.value = true;
        }
    }
};

const removeAllPlygon = () => {
    if (props.mapType === 1) {
        okDisabled.value = true;
    }
    map.clearMap();
    overlays = [];
    paths = [];
};

const poiPickerReady = (poiPicker) => {
    if (props.searchKey) {
        poiPicker.onCityReady(function () {
            poiPicker.searchByKeyword(props.searchKey);
        });
    }
    data.poiPicker = poiPicker;

    var marker = new AMap.Marker();
    var infoWindow = new AMap.InfoWindow({
        offset: new AMap.Pixel(0, -20),
    });

    //选取了某个POI
    poiPicker.on('poiPicked', function (poiResult) {
        var source = poiResult.source,
            info = {
                source: source,
                id: poi.id,
                name: poi.name,
                location: poi.location.toString(),
                address: poi.address,
            };
        poi = poiResult.item;
        if (props.mapType === 0) {
            okDisabled.value = false;
        }
        data.input = poi.name;
        marker.setMap(data.map);
        infoWindow.setMap(data.map);

        marker.setPosition(poi.location);
        infoWindow.setPosition(poi.location);
        tipTxt.value = JSON.stringify(info, null, 2);

        infoWindow.setContent('位置信息: <pre>' + JSON.stringify(info, null, 2) + '</pre>');
        infoWindow.open(data.map, marker.getPosition());

        map.setCenter(marker.getPosition());
    });
};

const getClickInfo = () => {
    this.map.clearMap();
    let lng = e.lnglat.getLng();
    let lat = e.lnglat.getLat();
    console.log(lng, lat);
    if (!!lng && !!lat) {
        addMarker(lng, lat);
        getAddressName(lng, lat);
    } else {
        this.address = {};
        ElMessage({
            message: '获取坐标点失败！',
            type: 'error',
        });
    }
};
const addMarker = (lng, lat) => {
    const markerInfo = {
        position: new this.aMap.LngLat(lng, lat),
    };
    const marker = new this.aMap.Marker(markerInfo);
    map.add(marker);
};
const getAddressName = (lng, lat) => {
    let geocoder = new this.aMap.Geocoder({ city: '全国' });
    geocoder.getAddress([lng, lat], function (status, result) {
        // console.log(status, result);
        if (status === 'complete' && result.info === 'OK') {
            const regeocode = _.get(result, 'regeocode', {});
            this.address = {
                lng,
                lat,
                district: regeocode.addressComponent.district,
                township: regeocode.addressComponent.township,
                street: regeocode.addressComponent.street,
                streetNumber: regeocode.addressComponent.streetNumber,
                full: regeocode.formattedAddress,
            };
        } else {
            ElMessage({
                message: '获取坐标点失败！',
                type: 'error',
            });
        }
    });
};
const handleConfirm = () => {
    if (props.mapType === 0) {
        //点
        console.log('poi :>> ', poi);
        if (!_.isEmpty(poi.name)) {
            $emits('mapConfirm', poi);
        } else {
            ElMessage({
                message: '请选择坐标后再提交',
                type: 'warning',
            });
        }
    } else if (props.mapType === 1) {
        //面
        $emits('mapConfirm', JSON.stringify(paths));
    } else if (props.mapType === 2) {
        //线
        $emits('mapConfirm', JSON.stringify(overlays));
    }
};
const handleCancel = () => {
    $emits('mapClose', false);
};

const openMouseTool = (mouseTool) => {
    if (props.mapType === 2) {
        mouseTool.polyline({
            strokeColor: '#4169E1',
            //同Polyline的Option设置
        });
    } else if (props.mapType === 1) {
        mouseTool.polygon({
            fillColor: '#00b0ff',
            strokeColor: '#80d8ff',
            //同Polygon的Option设置
        });
    }
};

var editors = [];
const closeEditor = () => {
    openMouseTool(mouseTool);
    editors.forEach((item) => {
        item.close();
    });
    console.log('overlays :>> ', overlays);
};
const editLine = () => {
    mouseTool.close(false);
    editors = [];
    overlays.forEach((item) => {
        var polyEditor;
        if (props.mapType === 1) {
            polyEditor = new AMap.PolygonEditor(map);
            polyEditor.addAdsorbPolygons(overlays);
            polyEditor.setTarget(item);
            polyEditor.open();
        } else if (props.mapType === 2) {
            // var polyEditor = new AMap.PolyEditor(map, polygon)
            polyEditor = new AMap.PolylineEditor(map);
            polyEditor.setTarget(item);
            polyEditor.open();
        }
        editors.push(polyEditor);
    });
};
</script>

<style scoped></style>
